package com.supplychainapi.service.impl;

import com.alibaba.fastjson.JSON;
import com.joindata.inf.common.basic.exceptions.ServiceException;
import com.supplychainapi.common.enums.ExceptionMessage;
import com.supplychainapi.common.exception.ExceptionManager;
import com.supplychainapi.dao.prod.*;
import com.supplychainapi.domain.SeqNoType;
import com.supplychainapi.domain.TableInfo;
import com.supplychainapi.domain.treeBuild.TreeBuildType;
import com.supplychainapi.model.ScmTbseqno;
import com.supplychainapi.model.Tbparamvalue;
import com.supplychainapi.service.TbSeqNoService;
import com.supplychainapi.utils.Constants;
import com.supplychainapi.utils.DateUtils;
import com.supplychainapi.utils.RegexUtils;
import com.supplychainapi.utils.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.supplychainapi.domain.treeBuild.TreeBuildType.Employee;

/**
 * Created by wangziqi on 2017/10/11.
 */
@Service
public class TbSeqNoServiceImpl implements TbSeqNoService {
    private Logger logger = LogManager.getLogger(this.getClass());
    @Autowired
    ScmTbseqnoMapper tbseqnoMapper;

    @Autowired
    ScmTbsupplierMapper tbsupplierMapper;


    @Autowired
    ScmTbtreebuildMapper tbtreebuildMapper;

    @Autowired
    ScmTbmaterialMapper tbmaterialMapper;

    @Autowired
    ScmTbstorageMapper tbstorageMapper;

    @Autowired
    ScmTbcustMapper tbcustMapper;

    @Autowired
    TbstaffMapper tbstaffMapper;

    @Autowired
    TbparamvalueMapper tbparamvalueMapper;


    /**
     * 同步锁对象
     */
    private Object lock = new Object();


    /**
     * 员工表类型
     */
    public final static Integer SEQNO_STAFF = 1;

    /**
     * 仓库类型
     */
    public final static Integer SEQNO_STORAGE = 2;

    /**
     * 供应商类型
     */
    public final static Integer SEQNO_SUPPLIER = 3;

    /**
     * 客户类型
     */
    public final static Integer SEQNO_CUST = 4;

    /**
     * 物料类型
     */
    public final static Integer SEQNO_MATERIAL = 5;

    /**
     * 部门ID
     */
    public final static Integer SEQNO_DEPARTMENT = 6;

    /**
     * 验收异常类型
     */
    public final static Integer SEQNO_CHECKEXCEPT = 7;

    /**
     * 计量单位
     */
    public final static Integer SEQNO_UNIT = 8;

    /**
     * 物料分类
     */
    public final static Integer SEQNO_TREE_MATERIAL = 9;

    /**
     * 供应商分类
     */
    public final static Integer SEQNO_TREE_SUPPLIER = 10;

    /**
     * 客户分类
     */
    public final static Integer SEQNO_TREE_CUST = 11;

    /**
     * 角色
     */
    public final static Integer SEQNO_ROLE = 12;

    /**
     * 模板
     */
    public final static Integer SEQNO_TEMPLET = 13;

    @Override
    public ScmTbseqno insert(ScmTbseqno model,String shopGuid) throws ServiceException{
        // 是否是含中文
        if(!RegexUtils.isENG_NUM_(model.getFiSeqNo())){
            throw ExceptionMessage.code_error_param.getServiceException();
        }
        logger.info("insert.ScmTbseqno :{},shopid:{}", JSON.toJSON(model), shopGuid);
        model.setFsUpdateTime(new Date());
        model.setFsShopGUID(shopGuid);
        String regEx = "[^0-9]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(model.getFiSeqNo());
        model.setFiSeqNo(String.valueOf(m.replaceAll(" ").trim()));
//        if (model.getFsCls().equals(TreeBuildType.Material.name())) {//物料
//            String max = tbmaterialMapper.getMaxCode(model.getFsShopGUID());
//            check(max, model);
//        }
//        if (model.getFsCls().equals(TreeBuildType.Supplier.name())) {//供应商
//            String max = tbsupplierMapper.getMaxCode(model.getFsShopGUID());
//            check(max, model);
//        }
//        if (model.getFsCls().equals(TreeBuildType.Warehouse.name())) {//仓库
//            String max = tbstorageMapper.getMaxCode(model.getFsShopGUID());
//            check(max, model);
//        }
//        if (model.getFsCls().equals(TreeBuildType.Cust.name())) {//客户
//            String max = tbcustMapper.getMaxCode(model.getFsShopGUID());
//            check(max, model);
//        }
//        if (model.getFsCls().equals(TreeBuildType.Material_Class.name())) {//物料分类
//            String max =tbtreebuildMapper.getCode(model.getFsShopGUID(),TreeBuildType.Material.name());
//            check(max, model);
//        }
//        if (model.getFsCls().equals(TreeBuildType.Supplier_Class.name())) {//供应商分类
//            String max =tbtreebuildMapper.getCode(model.getFsShopGUID(),TreeBuildType.Supplier.name());
//            check(max, model);
//        }
//        if (model.getFsCls().equals(TreeBuildType.Cust_Class.name())) {//客户分类
//            String max =tbtreebuildMapper.getCode(model.getFsShopGUID(),TreeBuildType.Cust.name());
//            check(max, model);
//        }
//        if (model.getFsCls().equals(TreeBuildType.Employee.name())) {//员工
//            String max =tbstaffMapper.getMaxCode(model.getFsShopGUID());
//            check(max, model);
//        }
        boolean isExit = isExit(model);
        if (!isExit) {
            int i = tbseqnoMapper.insert(model);
            if (i <= 0) {
                throw ExceptionMessage.operation_failed.getServiceException();
            }
        }
        return model;
    }

    @Override
    public boolean isExit(ScmTbseqno model) {
        model.setFsUpdateTime(new Date());
        int i =tbseqnoMapper.updateByCls(model);
        return i > 0;
    }

    @Override
    public boolean update(ScmTbseqno model) throws ServiceException{
        model.setFsUpdateTime(new Date());
        int i =tbseqnoMapper.updateByShopIdAndCls(model);
        return i > 0;
    }

    @Override
    public boolean delete(ScmTbseqno model) throws ServiceException{
        int i=tbseqnoMapper.delete(model);
        return i > 0;
    }

    @Override
    public String selectSeqNo(ScmTbseqno model) throws ServiceException{
//        if(StringUtils.isBlank(model.getFiSeqNo())){
//            String code=  tbseqnoMapper.selectSeqNo(model);
//            code=StringUtil.autoGenericCode(code,code==null?3:code.length());
//            model.setFiSeqNo(code);
//        }
//
//        model.setFsUpdateTime(new Date());
//        model=insert(model,model.getFsShopGUID());
        String seqno = getNo(conversion(model.getFsCls()), model.getFsShopGUID());
        logger.info("生成code,类型:{},生产编号:{}", model.getFsCls(), seqno);
        return model.getFiSeqNo();
    }

    private Integer conversion(String type) {
        if (TreeBuildType.Cust.name().equals(type)) {

            return SeqNoType.SEQNO_CUST.getCode();
        }
        if (TreeBuildType.Supplier.name().equals(type)) {

            return SeqNoType.SEQNO_SUPPLIER.getCode();
        }
        if (TreeBuildType.Material.name().equals(type)) {

            return SeqNoType.SEQNO_MATERIAL.getCode();
        }
        if (TreeBuildType.Cust_Class.name().equals(type)) {

            return SeqNoType.SEQNO_TREE_CUST.getCode();
        }
        if (TreeBuildType.Material_Class.name().equals(type)) {

            return SeqNoType.SEQNO_TREE_MATERIAL.getCode();
        }
        if (TreeBuildType.Supplier_Class.name().equals(type)) {

            return SeqNoType.SEQNO_TREE_SUPPLIER.getCode();
        }
        if (TreeBuildType.Employee.name().equals(type)) {

            return SeqNoType.SEQNO_STAFF.getCode();
        }
        if (TreeBuildType.Warehouse.name().equals(type)) {

            return SeqNoType.SEQNO_STORAGE.getCode();
        }
        return 0;
    }

    /**
     * 是不是大于最大值
     * @param max       最大值
     * @param model     当前值对象
     * @return
     */
    private void check(String max,ScmTbseqno model) throws ServiceException {
        if (StringUtils.isBlank(model.getFiSeqNo())) {
            throw ExceptionMessage.missing_param.getServiceException();
        }
        if (StringUtils.isBlank(max)) {
            max = model.getFiSeqNo();
        }
        if (!RegexUtils.isENG_NUM_(model.getFiSeqNo())) {
            throw ExceptionMessage.code_error_param.getServiceException();
        }
        String regEx = "[^0-9]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(max);
        max = String.valueOf(m.replaceAll(" ").trim());
        Long a = Long.valueOf(max);
        Long b = Long.valueOf(model.getFiSeqNo());
        update(model);
        if (a >= b) {
            model.setFiSeqNo(String.valueOf(a));
            update(model);
//                throw ExceptionMessage.code_error.getServiceException();
            model.setFiSeqNo(StringUtil.autoGenericCode(String.valueOf(a), String.valueOf(a).length()));

        }

    }


    private void checkCode(String max, ScmTbseqno model) throws ServiceException {
        if (StringUtils.isBlank(model.getFiSeqNo())) {
            throw ExceptionMessage.missing_param.getServiceException();
        }
        if (StringUtils.isBlank(max)) {
            max = model.getFiSeqNo();
            return;
        }
        if (!RegexUtils.isENG_NUM_(model.getFiSeqNo())) {
            throw ExceptionMessage.code_error_param.getServiceException();
        }
        String regEx = "[^0-9]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(max);
        max = String.valueOf(m.replaceAll(" ").trim());
        Long a = Long.valueOf(max);
        Long b = Long.valueOf(model.getFiSeqNo());
        boolean bool = update(model);
        if (!bool)
            insert(model, model.getFsShopGUID());
        if (a >= b) {
            model.setFiSeqNo(String.valueOf(a));
            boolean isUpdate = update(model);
            if (!isUpdate)
                insert(model, model.getFsShopGUID());
            throw ExceptionMessage.code_error.getServiceException();
        }
    }


    @Deprecated
    @Override
    public void checkCode(ScmTbseqno model) throws ServiceException {
        if (model.getFsCls().equals(TreeBuildType.Material.name())) {//物料
//            String max = tbmaterialMapper.getMaxCode(model.getFsShopGUID());
//            checkCode(max, model);
            checkCode(model.getFiSeqNo(), SeqNoType.SEQNO_MATERIAL.getCode(), model.getFsShopGUID());
        }
        if (model.getFsCls().equals(TreeBuildType.Supplier.name())) {//供应商
//            String max = tbsupplierMapper.getMaxCode(model.getFsShopGUID());
            checkCode(model.getFiSeqNo(), SeqNoType.SEQNO_SUPPLIER.getCode(), model.getFsShopGUID());
        }
        if (model.getFsCls().equals(TreeBuildType.Warehouse.name())) {//仓库
//            String max = tbstorageMapper.getMaxCode(model.getFsShopGUID());
            checkCode(model.getFiSeqNo(), SeqNoType.SEQNO_STORAGE.getCode(), model.getFsShopGUID());
        }
        if (model.getFsCls().equals(TreeBuildType.Cust.name())) {//客户
//            String max = tbcustMapper.getMaxCode(model.getFsShopGUID());
            checkCode(model.getFiSeqNo(), SeqNoType.SEQNO_CUST.getCode(), model.getFsShopGUID());
        }
        if (model.getFsCls().equals(TreeBuildType.Material_Class.name())) {//物料分类
            //String max =tbtreebuildMapper.getCode(model.getFsShopGUID(),TreeBuildType.Material.name());
            checkCode(model.getFiSeqNo(), SeqNoType.SEQNO_TREE_MATERIAL.getCode(), model.getFsShopGUID());
        }
        if (model.getFsCls().equals(TreeBuildType.Supplier_Class.name())) {//供应商分类
//            String max =tbtreebuildMapper.getCode(model.getFsShopGUID(),TreeBuildType.Supplier.name());
            checkCode(model.getFiSeqNo(), SeqNoType.SEQNO_TREE_SUPPLIER.getCode(), model.getFsShopGUID());
        }
        if (model.getFsCls().equals(TreeBuildType.Cust_Class.name())) {//客户分类
//            String max =tbtreebuildMapper.getCode(model.getFsShopGUID(),TreeBuildType.Cust.name());
            checkCode(model.getFiSeqNo(), SeqNoType.SEQNO_TREE_CUST.getCode(), model.getFsShopGUID());
        }
        if (model.getFsCls().equals(Employee.name())) {//员工
//            String max =tbstaffMapper.getMaxCode(model.getFsShopGUID());
            checkCode(model.getFiSeqNo(), SeqNoType.SEQNO_STAFF.getCode(), model.getFsShopGUID());
        }
    }

    @Override
    public void checkCode(String value, Integer type, String fsShopGUID) throws ServiceException {
        if (StringUtils.isBlank(value)) {
            throw ExceptionMessage.missing_param.getServiceException();
        }
        TableInfo tableInfo = getTableInfo(type, fsShopGUID);
        String Id = tbseqnoMapper.findMaxId(tableInfo);
        if (StringUtils.isNotBlank(Id) && StringUtils.isNotBlank(value)) {
            Long max = Long.parseLong(Id);
            Long now = Long.parseLong(value);
            tableInfo.setValue(value);
            int codeIsExit = tbseqnoMapper.codeIsExit(tableInfo);
            if (codeIsExit > 0) {
                throw ExceptionMessage.code_same.getServiceException();
            }
//            if (now <= max) {
//                throw ExceptionMessage.code_error.getServiceException();
//            }
        }
    }

    @Override
    public String getNo(Integer type, String fsShopGUID) {
        TableInfo tableInfo = getTableInfo(type, fsShopGUID);
        String Id = tbseqnoMapper.findMaxId(tableInfo);
        // 是否自增
        if (tableInfo.isAutoInc()) {
            if (org.apache.commons.lang.StringUtils.isBlank(Id)) {
                return "1001";
            } else {
                Id = Id.replaceAll("^(0+)", "");
                if ((Long.parseLong(Id) + 1) < 1001) {
                    return "1001";
                }
                return String.valueOf(Long.parseLong(Id) + 1);
            }
        } else {
            if (org.apache.commons.lang.StringUtils.isBlank(Id)) {
                return "001";
            }
            Id = Id.replaceAll("^(0+)", "");
            // 填充0不足三位前面填充0
            Id = String.format("%0" + 3 + "d", (Long.parseLong(Id) + 1));
            return Id;
        }
    }


    private TableInfo getTableInfo(Integer type, String fsShopGUID) {
        TableInfo tableInfo = new TableInfo();
        switch (type) {
            case 1: // 员工
                tableInfo.setTable("tbstaff");
                tableInfo.setId("fsStaffId");
                tableInfo.setFiStatus(1);
                tableInfo.setAutoInc(false);
                break;
            case 2: // 仓库
                tableInfo.setTable("scm_tbstorage");
                tableInfo.setId("fsStorageId");
                tableInfo.setFiStatus(null);
                tableInfo.setAutoInc(false);
                break;
            case 3: // 供应商
                tableInfo.setTable("scm_tbsupplier");
                tableInfo.setId("fsSupplierId");
                tableInfo.setFiStatus(null);
                tableInfo.setAutoInc(false);
                break;
            case 4: // 客户
                tableInfo.setTable("scm_tbcust");
                tableInfo.setId("fsCustId");
                tableInfo.setFiStatus(null);
                tableInfo.setAutoInc(false);
                break;
            case 5: // 物料
                tableInfo.setTable("scm_tbmaterial");
                tableInfo.setId("fsMaterialId");
                tableInfo.setFiStatus(null);
                tableInfo.setAutoInc(false);
                break;
            case 6: // 部门
                tableInfo.setTable("tbdepartment");
                tableInfo.setId("fsDepartmentId");
                tableInfo.setFiStatus(1);
                tableInfo.setAutoInc(true);
                break;
            case 7: // 验收异常类型
                tableInfo.setTable("scm_tbcheckexcept");
                tableInfo.setId("fsCheckExceptId");
                tableInfo.setFiStatus(null);
                tableInfo.setAutoInc(true);
                break;
            case 8: // 计量单位
                tableInfo.setTable("scm_tbunit");
                tableInfo.setId("fsUnitId");
                tableInfo.setFiStatus(null);
                tableInfo.setAutoInc(true);
                break;
            case 9: // 物料分类
                tableInfo.setTable("scm_tbtreebuild");
                tableInfo.setId("fsNodeCode");
                tableInfo.setFiStatus(null);
                tableInfo.setAutoInc(false);
                tableInfo.setFsTreeTypeId("Material");
                break;
            case 10: // 供应商分类
                tableInfo.setTable("scm_tbtreebuild");
                tableInfo.setId("fsNodeCode");
                tableInfo.setFiStatus(null);
                tableInfo.setAutoInc(false);
                tableInfo.setFsTreeTypeId("Supplier");
                break;
            case 11: // 客户分类
                tableInfo.setTable("scm_tbtreebuild");
                tableInfo.setId("fsNodeCode");
                tableInfo.setFiStatus(null);
                tableInfo.setAutoInc(false);
                tableInfo.setFsTreeTypeId("Cust");
                break;
            case 12: // 角色ID
                tableInfo.setTable("tbrole");
                tableInfo.setId("fsRoleId");
                tableInfo.setFiStatus(1);
                tableInfo.setAutoInc(true);
                break;
            case 13: // 模板ID
                tableInfo.setTable("scm_tbtemplet");
                tableInfo.setId("fsTempletId");
                tableInfo.setFiStatus(1);
                tableInfo.setAutoInc(false);
        }
        tableInfo.setFsShopGUID(fsShopGUID);
        return tableInfo;
    }

    @Override
    public String getOrderNo(String fsParamId, String tableName, String fsShopGUID) {
        Tbparamvalue tbparamvalue = new Tbparamvalue();
        tbparamvalue.setFsparamid(fsParamId);
        tbparamvalue.setFsshopguid(fsShopGUID);
        tbparamvalue = tbparamvalueMapper.selectByPrimaryKey(tbparamvalue);
        String fiSeqNo = "";
        if (tbparamvalue != null) {
            // 前缀字
            String fsParamValue = tbparamvalue.getFsparamvalue();
            // 年
            String fsStr1 = tbparamvalue.getFsstr1();
            // 月
            String fsStr2 = tbparamvalue.getFsstr2();
            // 日
            String fsStr3 = tbparamvalue.getFsstr3();
            // 位数
            int fiInt1 = tbparamvalue.getFiint1();

            String orderNo_prefix = "";
            // 同步锁
            synchronized (lock) {
                // 勾选年
                if (StringUtils.equals(Constants.CONTANTS_STR_1, fsStr1)) {
                    orderNo_prefix = fsParamValue + DateUtils.getCurrentDate(DateUtils.PATTERN_DATE_YEAR);
                }
                // 勾选月
                if (StringUtils.equals(Constants.CONTANTS_STR_1, fsStr2)) {
                    orderNo_prefix = fsParamValue + DateUtils.getCurrentDate(DateUtils.PATTERN_DATE_MONTH);
                }
                // 勾选日
                if (StringUtils.equals(Constants.CONTANTS_STR_1, fsStr3)) {
                    orderNo_prefix = fsParamValue + DateUtils.getCurrentDate(DateUtils.PATTERN_DATE_DAY);
                }
                if (fiInt1 == Constants.CONTANTS_SHORT_0) {
                    fiInt1 = Constants.CONTANTS_SHORT_3;
                }

                ScmTbseqno scmTbseqno_select = new ScmTbseqno();
                scmTbseqno_select.setFsCls(tableName + "_" + orderNo_prefix);
                scmTbseqno_select.setFsItem(orderNo_prefix);
                scmTbseqno_select.setFiInt1(fiInt1);
                scmTbseqno_select.setFsShopGUID(fsShopGUID);
                scmTbseqno_select.setFsUpdateTime(new Date());
                ScmTbseqno scmTbseqno = tbseqnoMapper.selectByCondition(scmTbseqno_select);
                if (scmTbseqno != null) {
                    // 返回单据编码
                    fiSeqNo = orderNo_prefix + scmTbseqno.getFiSeqNo();
                    // 生成下个单据编码
                    int new_fiSeqNo = Integer.parseInt(scmTbseqno.getFiSeqNo()) + 1;
                    String result = String.format("%0" + fiInt1 + "d", new_fiSeqNo);
                    // 流水号超限
                    if (result.length() > fiInt1) {
                        throw ExceptionManager.fail("流水号位数超限");
                    }
                    scmTbseqno.setFiSeqNo(result);
                    tbseqnoMapper.updateByCondition(scmTbseqno);
                } else {
                    // 返回单据编码
                    fiSeqNo = orderNo_prefix + String.format("%0" + fiInt1 + "d", 1);
                    // 保存下个单据编码
                    scmTbseqno_select.setFiSeqNo(String.format("%0" + fiInt1 + "d", 2));
                    tbseqnoMapper.insertSelective(scmTbseqno_select);
                }
            }
        } else {
            throw ExceptionManager.fail("单据编码未初始化设置");
        }
        return fiSeqNo;
    }
}
